using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using CSF.Communications.Sdp.ServiceLogic.Entities;
using CSF.Communications.Sdp.ServiceLogic.Exceptions;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using System.IO;
using System.Globalization;

namespace CSF.Communications.Sdp.ServiceLogic.Utilities
{
   public class MessageFactory
   {

       #region Members
       private MapServiceProvider _msp;
       #endregion

       #region Constructor
       /// <summary>
       /// 
       /// </summary>
       public MessageFactory()
       {
           _msp = new MapServiceProvider();
       }
       #endregion

       #region ConstructVASInternalrequest
       /// <summary>
       /// 
       /// </summary>
       /// <param name="mid"></param>
       /// <param name="serviceID"></param>
       /// <returns></returns>
       public VasRequestInternal ConstructVASInternalrequest(CSF_MID mid, string serviceID, string action)
       {
           VasRequestInternal request = new VasRequestInternal();

           try
           {
               request.Parameters = new VasRequestInternalParameters();

               string[] serviceID_Splitter = mid.RoutingData.NextStates.Split('.');

               string[] vasState_Splitter = serviceID_Splitter[1].Split('-');

               string vasid = serviceID_Splitter[0];

               string endstate = String.Empty;
               string vasaction = action;
               string startstate = String.Empty;

               if (vasState_Splitter.Length > 0)
               {


                   vasaction = vasState_Splitter[0];

                   if (vasState_Splitter.Length > 1 && vasState_Splitter[1] != null)
                   {
                       startstate = vasState_Splitter[1];
                   }


                   if (vasState_Splitter.Length > 2 && vasState_Splitter[2] != null)
                   {
                       endstate = vasState_Splitter[2];
                   }
               }

               foreach (ServiceLogicPayloadTypeVASData vasdata in mid.VASDataCollection)
               {
                   if (vasdata.VASID.Equals(serviceID))
                   {
                       if (vasdata.VASAction == String.Empty || vasdata.VASAction.Equals(action))
                       {
                           request.Parameters.Any = vasdata.VasRequest.Parameters.Any;
                           request.Action = vasaction;
                           request.EndState = endstate;
                           request.StartState = startstate;
                           request.VASAction = vasaction;
                       }
                   }

               }

               
           }
           catch (Exception ex)
           {

               throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPConstructVASInternalException), ex.Message);
           }
           return request;

       }
       #endregion

       #region ConstructDynamicMID
       /// <summary>
       /// 
       /// </summary>
       /// <param name="mid"></param>
       /// <param name="serviceID"></param>
       /// <returns></returns>
       public CSF_MID ConstructDynamicMID(CSF_MID mid)
       {
           CSF_MID mid_dynamic;
           System.Data.DataSet ds = null;
           int IsComplex = 0;
           string map = null;
           DataServiceProvider _dsp = new DataServiceProvider();

           try
           {
            
               ds = _dsp.GetDynamicMappingfromDatabase(mid.RoutingData.Maps, out map, out IsComplex);

               if (IsComplex == 0)
               {
                   mid_dynamic = _msp.GetSimpleDynamicMap(mid.RoutingData.Maps, mid, ds);
               }
               else
               {
                   mid_dynamic = CSF_MID.DeSerializeObject(_msp.GetDynamicXML(mid.RoutingData.Maps, mid.SerializeObject()));
               }

           }
           catch (Exception ex)
           {
               throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPDynamicMapTrnsformationException), ex.Message);
           }
           return mid_dynamic;

       }


       #endregion

       #region PrepareRequestToVas
       /// <summary>
       /// 
       /// </summary>
       public XmlDocument PrepareRequestToVas(VasRequestInternal request, string serviceID, string action)
       {
           XmlDocument doc;
           XmlNode node;
           XmlDocument requestXML = new XmlDocument();

           try
           {

               switch (serviceID)
               {

                   case "CSF_IdM_OrganizationManager":

                       switch (action)
                       {
                           case "CreateOrganization":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='OrganizationManagerCreate']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           case "DeleteOrganization":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='OrganizationManagerDelete']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;

                           case "UpdateOrganization":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='OrganizationManagerUpdate']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;

                           default:
                               break;
                       }

                       break;

                   case "CSF_PM_UserRoleManager":
                       switch (action)
                       {
                           case "CheckUserInRole":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='UserToRolesAddRequest']");
                               UserToRolesAddRequest roleAddRequest = UserToRolesAddRequest.DeSerializeObject(node.ParentNode.InnerXml);
                               IsUserInRoleRequest isInRoleRequest = new IsUserInRoleRequest();
                               isInRoleRequest.UserId = roleAddRequest.UserId;
                               isInRoleRequest.RoleId = roleAddRequest.RoleIds[0];
                               requestXML.LoadXml(isInRoleRequest.SerializeObject());
                               break;
                           default:
                               break;

                       }
                       break;

                   case "CSF_PM_RoleManager":
                       switch (action)
                       {
                           case "CreateRoles":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='RolesAddRequest']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           default:
                               break;
                       }
                       break;

                   case "CSF_IdM_UserManager":
                       switch (action)
                       {
                           case "CreateUser":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='UserManagerCreate']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           case "DeleteUser":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='UserManagerDelete']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           default:
                               break;
                       }
                       break;

                   case "CSF_IdM_UserMapManager":
                       switch (action)
                       {
                           case "CreateMap":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='UserMapManagerCreateMap']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           default:
                               break;
                       }
                       break;

                   case "CSF_PM_UserServiceMapping":
                       switch (action)
                       {
                           case "CreateMapping":
                               doc = new XmlDocument();
                               doc.LoadXml(request.SerializeObject());
                               node = doc.SelectSingleNode("//*[local-name()='Parameters' and namespace-uri()='']/*[local-name()='UserServiceMappingAddRequest']");
                               requestXML.LoadXml(node.ParentNode.InnerXml);
                               break;
                           default:
                               break;
                       }
                       break;
                   default:
                       ModifyStateRequest msrequest = this.PrepareModifyStateRequest(request, serviceID, action);
                       requestXML.LoadXml(msrequest.SerializeObject());
                       break;
               }
               return requestXML;
           }
           catch (ApplicationException appEx)
           {
               throw appEx;
           }
           catch (Exception ex)
           {
               ExceptionManager.Publish(ex, Convert.ToInt32(SDPSystemError.SDPSystemException));
               throw new ApplicationException(ex.Message);
           }
           
       }
       #endregion

       #region PrepareModifyStateRequest
       /// <summary>
       /// 
       /// </summary>
       /// <param name="request"></param>
       /// <param name="serviceID"></param>
       /// <param name="action"></param>
       /// <returns></returns>
       public ModifyStateRequest PrepareModifyStateRequest(VasRequestInternal request, string serviceID, string action)
       {
           ModifyStateRequest msrequest = new ModifyStateRequest();

           MapServiceProvider msp = new MapServiceProvider();

           try
           {
               msrequest.Target = serviceID;
               msrequest.Identifier = System.Configuration.ConfigurationSettings.AppSettings["TokenUserName"].ToString();
               msrequest.Action = request.StartState;
               msrequest.EndState =request.EndState;
               msrequest.StartState = "Start";
               msrequest.Parameters = request.Parameters;
               return msrequest;
           }
           catch (ApplicationException appEx)
           {
               throw appEx;
           }
           catch (Exception ex)
           {
               ExceptionManager.Publish(ex, Convert.ToInt32(SDPSystemError.SDPSystemException));
               throw new ApplicationException(ex.Message);
           }
           
       }
       #endregion

       #region GetServiceLogicCompletion
       /// <summary>
       /// 
       /// </summary>
       /// <param name="mid"></param>
       /// <returns></returns>
       public ServiceLogicCompletionStatus GetServiceLogicCompletion(CSF_MID mid, String errorMessage)
       {
           ServiceLogicCompletionStatus response = new ServiceLogicCompletionStatus();

           try
           {

              if (mid.RoutingData.RulePolicyStatus.ToString()== "completed") 
               {
                   int mid_length = mid.VASDataCollection.Length;
                   response.VASCallStatusCollection = new ServiceLogicCompletionStatusVASCallStatus[mid_length];

                  foreach (ServiceLogicPayloadTypeVASData vasdata in mid.VASDataCollection)
                   {
                       response.VASCallStatusCollection[mid.VASDataCollection.Length - mid_length] = new ServiceLogicCompletionStatusVASCallStatus();
                       response.VASCallStatusCollection[mid.VASDataCollection.Length - mid_length].VASID = vasdata.VASID;
                       response.VASCallStatusCollection[mid.VASDataCollection.Length - mid_length].VASServiceUUID = vasdata.VASServiceUUID;
                       response.VASCallStatusCollection[mid.VASDataCollection.Length - mid_length].ResultCode = vasdata.VasResponse[0].ResultCode;
                       mid_length--;
                   }
                   response.RulePolicyStatus = mid.RoutingData.RulePolicyStatus;
                   response.ResultCode = mid.RoutingData.ResultCodeToSbe;
                   response.ErrorMessage = mid.RoutingData.ErrorMessageToSbe;
               }
               else
               {
                   response.RulePolicyStatus = mid.RoutingData.RulePolicyStatus;
                   response.ErrorMessage = mid.RoutingData.ErrorMessageToSbe;
                   response.ResultCode = mid.RoutingData.CurrentResultCode;
               
               }

           }
           catch (Exception ex)
           {
               throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPServiceLogicCompletionException), ex.Message);
           }
           return response;


       }
       #endregion

       #region ConstructDynamicMID
       /// <summary>
       /// 
       /// </summary>
       /// <param name="mid"></param>
       /// <param name="type"></param>
       /// <returns></returns>
       public CSF_MID ConstructDynamicMID(CSF_MID mid_initial, string type)
       {
           CSF_MID mid_final = null;
           try
           {

               XmlDocument mid_intermediate = new XmlDocument();
               mid_initial.RoutingData.IsUSMRequired = false;
               mid_initial.RoutingData.IsSSORequired = false;

               ServiceLogicPayloadTypeVASData _vasData = new ServiceLogicPayloadTypeVASData();
               string serviceUUID = string.Empty;
               string userId = string.Empty;
               string orgId = string.Empty;
               string password = string.Empty;
               int vasCount = mid_initial.VASDataCollection.Length;

               mid_final = new CSF_MID();
               mid_final.CSFData = mid_initial.CSFData;

               mid_final.CSFProfile = mid_initial.CSFProfile;

               mid_final.RoutingData = mid_initial.RoutingData;

               mid_initial.ServiceLogicStatus = mid_initial.ServiceLogicStatus;


               mid_final.VASDataCollection = new ServiceLogicPayloadTypeVASData[vasCount + 1];

               mid_intermediate.LoadXml(mid_initial.SerializeObject());

               XmlNode node = mid_intermediate.SelectSingleNode("//*[local-name()='VASDataCollection']/*[local-name()='VASData'][VASID='CSF_IdM_UserManager']/*[local-name()='VasRequest']/*[local-name()='Parameters']/*[local-name()='UserManagerCreate']/*[local-name()='UserAccount']/*[local-name()='UserId']");
               userId = node.InnerXml.ToString();

               node = mid_intermediate.SelectSingleNode("//*[local-name()='VASDataCollection']/*[local-name()='VASData'][VASID='CSF_IdM_UserManager']/*[local-name()='VasRequest']/*[local-name()='Parameters']/*[local-name()='UserManagerCreate']/*[local-name()='OrganizationId']");
               orgId = node.InnerXml.ToString();

               node = mid_intermediate.SelectSingleNode("//*[local-name()='VASDataCollection']/*[local-name()='VASData'][VASID='SDKService']/*[local-name()='VasRequest']/*[local-name()='Parameters']/*[local-name()='password']");
               
               if(node!=null)
               password = node.InnerXml.ToString();

               int i = 0;




           foreach (ServiceLogicPayloadTypeVASData vasdata in mid_initial.VASDataCollection)
           {

                mid_final.VASDataCollection[i] = vasdata;

                if (vasdata.VASServiceUUID != null && vasdata.VASServiceUUID == mid_final.RoutingData.SsoApplicationName)
                {
                    foreach (XmlElement element in vasdata.VasRequest.Parameters.Any)
                    {
                        if (element.Name.Equals("password"))
                        {
                            password = element.InnerXml;
                        }
                        
                    }
                }

                i++;

           }


               if (type.Equals("IsSSORequired"))
               {

                   _vasData.VASID = "CSF_IdM_UserMapManager";

                   UserMapManagerCreateMap usermap = new UserMapManagerCreateMap();

                   usermap.UserId = userId;
                   usermap.ApplicationId = mid_final.RoutingData.SsoApplicationName;
                   usermap.ApplicationUserCredential = password;
                   usermap.ApplicationCredentialType = "password";

                   XmlDocument tempdoc = new XmlDocument();
                   tempdoc.LoadXml(this.SerializeObject(usermap));

                   _vasData.VasRequest = new ServiceLogicPayloadTypeVASDataVasRequest();
                   _vasData.VasRequest.Parameters = new ParametersType();

                   XmlElement[] elem = new XmlElement[1];

                   elem[0] = (System.Xml.XmlElement) (tempdoc.GetElementsByTagName("UserMapManagerCreateMap")[0]);
                   _vasData.VasRequest.Parameters.Any = elem;

                

               }
               else if (type.Equals("IsUSMRequired"))
               {
                   _vasData.VASID = "CSF_PM_UserServiceMapping";
                   UserServiceMappingAddRequest request = new UserServiceMappingAddRequest();
                   request.UserId = userId;
                   request.ServiceContext = orgId;
                   request.ServiceId = mid_final.RoutingData.UsmServiceId;
                   XmlDocument tempdoc = new XmlDocument();
                   tempdoc.LoadXml(this.SerializeObject(request));
                   _vasData.VasRequest = new ServiceLogicPayloadTypeVASDataVasRequest();
                   _vasData.VasRequest.Parameters = new ParametersType();
                   XmlElement[] elem = new XmlElement[1];
                   elem[0] = (System.Xml.XmlElement) (tempdoc.GetElementsByTagName("UserServiceMappingAddRequest")[0]);
                   _vasData.VasRequest.Parameters.Any = elem;
               }
               
               if (_vasData != null)
               {
                   mid_final.VASDataCollection[vasCount] = _vasData;
               }

           }
           catch(Exception ex)
           {
           }
           return mid_final;
       }
       #endregion

       #region SerializeObject
       /// <summary>
       /// This method returns an xml representation of the object
       /// </summary>
       /// <returns>The xml resprestation as Srting</returns>
       public string SerializeObject(object obj)
       {
           StringBuilder serialBuilder;
           StringWriter serialWriter;
           XmlSerializer messageSerializer;
           XmlSerializerNamespaces xmlNamespaces = null;
           try
           {
               serialBuilder = new StringBuilder(1000);
               serialWriter = new StringWriter(serialBuilder, CultureInfo.InvariantCulture);
               messageSerializer = new XmlSerializer(obj.GetType());
               messageSerializer.Serialize(serialWriter,obj);
               return serialWriter.ToString();
           }
           catch (Exception serializeObjectException)
           {
               throw (serializeObjectException);
           }
           finally
           {
               serialBuilder = null;
               serialWriter = null;
               messageSerializer = null;
           }
       }
       #endregion

   }
}
